package com.uhuibao.tmall.api.service.impl;


import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.uhuibao.tmall.api.domain.*;
import com.uhuibao.tmall.api.domain.vo.OrderChargeRequest;
import com.uhuibao.tmall.api.mapper.OrderMapper;
import com.uhuibao.tmall.api.service.IOrderService;
import com.uhuibao.tmall.common.annotation.DataSource;
import com.uhuibao.tmall.common.enums.DataSourceType;
import com.uhuibao.tmall.common.utils.DateUtils;
import com.uhuibao.tmall.common.utils.OkHttpClientUtils;
import com.uhuibao.tmall.constant.Constant;
import com.uhuibao.tmall.utils.MD5;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.annotations.Param;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;


/**
 * 订单相关 Service业务层处理
 *
 * @author haungzj
 * @date 2023-09-12
 */
@Service
public class OrderServiceImpl implements IOrderService {

    protected final Logger logger = LoggerFactory.getLogger(this.getClass());
    @Value("${chain.chainThirdApiUrl}")
    private String chainThirdApiUrl;

    @Value("${chain.account}")
    private String chainAccount;
    @Value("${chain.secret}")
    private String chainSecret;

    @Autowired
    private IOrderService orderService;
    @Autowired
    private OrderMapper orderMapper;


    /**
     * 获取链云去到帐号
     *
     * @param interCode
     * @return
     */
    public Map<String, Object> getGoodsInfo(@Param("interCode") String interCode) {
        return orderMapper.getGoodsInfo(interCode);
    }

    /**
     * 链云订单信息
     *
     * @param traceNo
     * @return
     */
    public Map<String, Object> getChainOrderInfo(@Param("traceNo") String traceNo) {
        return orderMapper.getChainOrderInfo(traceNo);
    }

    /**
     * 整理订单数据
     *
     * @return
     */
    public Map<String, Object> getChainTidyUpOrderInfo(String traceNo, String tmallNotifyUrl) {
        //查一下这个订单是不是本来就存在的 存在的话 走一下更新
        Map<String, Object> orderInfo = orderService.getChainOrderInfo(traceNo);
        if (orderInfo != null) {
            String orderNum = orderInfo.get("ORDER_NO").toString();

            String coopOrderStatus = null;
            String errDesc = null;
            //0创建中1已创建2成功3失败4接口异常失败
            int orderStatus = Integer.parseInt((String) orderInfo.get("STATUS"));
            if (orderStatus < 2) {
                coopOrderStatus = "UNDERWAY";
                errDesc = "订单充值中";
            }
            if (orderStatus == 2) {
                coopOrderStatus = "SUCCESS";
                errDesc = "订单充值成功";
            }
            if (orderStatus > 2) {
                coopOrderStatus = "FAILED";
                errDesc = "订单充值失败";
            }
            if (tmallNotifyUrl != null) {
                //更新一下回调地址字段
                updateOrderTmallNotifyUrl(orderNum, tmallNotifyUrl);
            }

            Map<String, Object> retMap = new HashMap<>();
            retMap.put("coopOrderNo", orderNum);
            retMap.put("coopOrderStatus", coopOrderStatus);
            retMap.put("errCode", coopOrderStatus);
            retMap.put("errDesc", errDesc);
            return retMap;
        }
        return null;
    }


    /**
     * 获取订单列表
     *
     * @return
     */
    public List<Map<String, Object>> getChainOrderList() {
        return orderMapper.getChainOrderList();
    }

    /**
     * 更新天猫的回调地址
     *
     * @param traceNo
     * @return
     */
    public int updateOrderTmallNotifyUrl(String orderNum, String tmallNotifyUrl) {
        return orderMapper.updateOrderTmallNotifyUrl(orderNum, tmallNotifyUrl);
    }

    /**
     * 更新是否已经回调过
     * @param orderNum
     * @return
     */
    public int updateOrderTmallIsCallback(String orderNum){
        return orderMapper.updateOrderTmallIsCallback(orderNum);
    }

    /**
     * 充值处理
     *
     * @param request
     * @return
     */
    public Map<String, Object> orderDeal(OrderChargeRequest request) throws IOException {
        //查询商品是否存在
        Map<String, Object> goodsInfo = orderService.getGoodsInfo(request.getSpuId().toString());
        if (goodsInfo == null) {
            Map<String, Object> retMap = new HashMap<>();
            retMap.put("errCode", "FAILED");
            retMap.put("errDesc", "无效的商品ID！");
            return retMap;

        }
        String tmallNotifyUrl = request.getNotifyUrl();
        logger.info("【回调地址】{}", tmallNotifyUrl);
        Integer productId = (Integer) goodsInfo.get("GOODS_ID");
        Integer supplierId = (Integer) goodsInfo.get("SUPPLIER_ID");
        logger.info("【supplierId】{}", supplierId);


        //中国联通跟移动
        int[] numbers = {Constant.SUUPLIERID_MOBILE, Constant.SUUPLIERID_UNICOM};
        boolean isOnePresent = Arrays.stream(numbers).anyMatch(n -> n == supplierId);
        if (!isOnePresent) {
            Map<String, Object> retMap = new HashMap<>();
            retMap.put("errCode", "FAILED");
            retMap.put("errDesc", "套餐运营商匹配有误！ 请联系供应商！");
            return retMap;
        }


        //判断订单是否已经存在，存在了 就直接返回订单状态
        Map<String, Object> orderInfo = orderService.getChainTidyUpOrderInfo(request.getTbOrderNo().toString(), tmallNotifyUrl);
        if (orderInfo != null) {
            return orderInfo;
        }

        //新订单获取旧订单没成功发货的 重新调用链云
        String now = DateUtils.getNow(null);
        JSONObject dataParam = new JSONObject();
        dataParam.put("phone", request.getAccountVal());
        dataParam.put("productId", productId);
        dataParam.put("traceNo", request.getTbOrderNo());
        dataParam.put("userId", 0);
        String sign = getChainSign(chainSecret, dataParam, now);

        //移动或者联通的接口名称
        String reqType = null;
        if (supplierId == Constant.SUUPLIERID_UNICOM) {
            reqType = "order_unicom_flow";
        }
        if (supplierId == Constant.SUUPLIERID_MOBILE) {
            reqType = "order_cmcc_flow";
        }

        Map<String, Object> reqParams = new TreeMap<>();
        reqParams.put("req_type", reqType);
        reqParams.put("account", chainAccount);
        reqParams.put("request_time", now);
        reqParams.put("data", dataParam);
        reqParams.put("sign", sign);

        //调用领科接口
        String postData = JSON.toJSONString(reqParams);
        String jsonData = OkHttpClientUtils.getInstance().postChainData(chainThirdApiUrl, postData);
        logger.info("【接口响应】：\r\n {}", jsonData);
        //下单成功
        Integer respCode = (Integer) JSONObject.parseObject(jsonData).get("resp_code");
        String respDesc = JSONObject.parseObject(jsonData).get("resp_desc").toString();
        if (respCode != 1) {
            Map<String, Object> retMap = new HashMap<>();
            retMap.put("errCode", "FAILED");
            retMap.put("errDesc", respDesc);
            return retMap;
        }
        JSONObject dataObj = (JSONObject) JSONObject.parseObject(jsonData).get("data");
        String orderNum = dataObj.get("orderNo").toString();

        //更新一下回调地址字段
        updateOrderTmallNotifyUrl(orderNum, tmallNotifyUrl);

        //重新查询一下 返回具体得订单状态信息
        Map<String, Object> retMap = new HashMap<>();
        retMap.put("coopOrderNo", orderNum);
        retMap.put("coopOrderStatus", "UNDERWAY");
        retMap.put("errCode", "UNDERWAY");
        retMap.put("errDesc", "订单充值中");
        return retMap;
    }

    /**
     * 生成签名
     *
     * @param secret 链云渠道密钥
     * @param param  参与签名的请求参数集
     * @param time   当前时间，格式yyyy-MM-dd HH:mm:ss
     * @return
     */
    private static String getChainSign(String secret, JSONObject param, String time) {
        StringBuilder sb = new StringBuilder();
        List<String> keys = new ArrayList<String>();
        keys.addAll(param.keySet());
        Collections.sort(keys);
        for (int i = 0; i < keys.size(); i++) {
            String key = keys.get(i);
            sb.append(key).append("=").append(param.getString(key)).append("&");
        }
        sb.append("key=").append(secret);
        System.out.println(sb.toString());
        String sign = MD5.enCodeStandard(secret + MD5.sha1(sb.toString()) + time).toUpperCase();
        return sign;
    }
}
